package edu.hawaii.senin.iclouds.controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Calendar;
import java.util.Observable;

import javax.swing.JFileChooser;

import edu.hawaii.senin.iclouds.basics.ReadConfigException;
import edu.hawaii.senin.iclouds.simple.Cloud;
import edu.hawaii.senin.iclouds.simple.CloudParametersMessage;
import edu.hawaii.senin.iclouds.util.TraffoFilter;
import edu.hawaii.senin.iclouds.view.View;

/**
 * Provides Controller component for iClouds project.
 * 
 * @author Pavel Senin.
 * 
 */
public class Controller
    extends Observable {

  /**
   * View that presents work for users.
   */
  private View view;

  /**
   * Cloud that does all simulation.
   */
  private Cloud model;

  /**
   * Stops running Cloud thread.
   */
  public boolean stopSimulation;

  /**
   * Instantiates controller.
   * 
   * @param model model to use.
   * @param view view implementation to use.
   */
  public Controller(Cloud model, View view) {

    // this.scheduler = new Scheduler();
    // new Thread(this.scheduler).start();
    // this.scheduler.addObserver(view);

    this.model = model;
    this.view = view;

    model.addObserver(view);
    this.addObserver(model);

    view.addLoadListener(new ConfigLoadListener());
    view.addLogListener(new LogListener());
    view.addRunListener(new RunListener());
    view.addStopListener(new StopListener());
    view.showGUI();
  }

  /**
   * Loads xml configuration by providing friendly File chooser.
   * 
   * @author Pavel Senin.
   * 
   */
  private class ConfigLoadListener implements ActionListener {
    /**
     * Contains the action performed event.
     * 
     * @param e the action event.
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {

      JFileChooser fc = new JFileChooser(System.getProperty("user.dir") + "/config");

      fc.addChoosableFileFilter(new TraffoFilter());
      fc.setAcceptAllFileFilterUsed(false);

      int returnVal = fc.showDialog(view.getJFrame(), "Attach");
      // Process the results.
      if (returnVal == JFileChooser.APPROVE_OPTION) {
        view.addToLog("controller : attaching file: " + fc.getSelectedFile() + ".\n");
        view.setConfigName(fc.getSelectedFile().getAbsolutePath());
        CloudParametersMessage cm = new CloudParametersMessage(); 
        try {
          cm.addParameter(CloudParametersMessage.CFGNAME, fc.getSelectedFile().getAbsolutePath());
          model.setParameters(cm);
        }
        catch (ReadConfigException e1) {
          e1.printStackTrace();
        }
      }
      else {
        assert true;
        view.addToLog("controller : attachment canceled by user.\n");
      }
      fc.setSelectedFile(null);
    }
  }

  /**
   * Selects log file using File chooser.
   * 
   * @author Pavel Senin.
   * 
   */
  private class LogListener implements ActionListener {
    /**
     * Contains the action performed event.
     * 
     * @param e the action event.
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {

      JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
      int returnVal = fc.showSaveDialog(view.getJFrame());
      if (returnVal == JFileChooser.APPROVE_OPTION) {
        File file = fc.getSelectedFile();
        if (file != null) { // if user did not cancel file dialog
          view.addToLog("controller : setting log file: " + fc.getSelectedFile() + ".\n");
          view.setLogName(fc.getSelectedFile().getAbsolutePath());
        }

      }
    }
  }

  /**
   * Provides listener for Run simulation button.
   * 
   * @author Pavel Senin.
   * 
   */
  private class RunListener implements ActionListener {
    /**
     * Contains the action performed event.
     * 
     * @param e the action event.
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {
      view.addToLog("controller: Running simulation at " + Calendar.getInstance().getTime());
      try {
        model.setParameters(view.getPhysicalParameters());
        if (model.modelReady()) {
          stopSimulation = false;
          new Thread(model).start();
        }
        else {
          view.addToLog("Model is not ready");
        }
      }
      catch (ReadConfigException e1) {
        e1.printStackTrace();
      }
    }
  }

  /**
   * Provides listener for the Stop simulation button.
   * 
   * @author Pavel Senin.
   * 
   */
  private class StopListener implements ActionListener {
    /**
     * Contains the action performed event.
     * 
     * @param e the action event.
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {
      view.addToLog("controller: Stopping simulation at " + Calendar.getInstance().getTime());
      stopSimulation = true;
      setChanged();
      notifyObservers(stopSimulation);
    }
  }

}
